/**
 * Copyright 2018 lenos
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.moshang.blog.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.moshang.blog.core.utils.PageUtil;
import com.moshang.blog.entity.activity.ActAssignee;
import com.moshang.blog.model.ActModel;
import com.moshang.blog.model.ProcessDefinition;
import com.moshang.blog.service.ActAssigneeService;
import com.moshang.blog.util.MyException;
import com.moshang.blog.util.RestResponse;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ModelQuery;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

/**
 * 流程管理 流程创建、发布 流程节点绑定角色/用户(绑定用户 开始ing)
 */
@Controller
@RequestMapping(value = "/act/")
public class ActivitiController{

    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private ActAssigneeService actAssigneeService;
    @Autowired
    private ObjectMapper objectMapper;
    @GetMapping("actUpdate/{id}")
    public String actUpdate(@PathVariable String id) {
        return "redirect:/static/modeler.html?modelId=" + id;
    }

    @GetMapping(value = "goAct")
    public String goAct(org.springframework.ui.Model model) {
        return "actList";
    }

    /**
     * 部署列表
     */
    @RequestMapping(value = "showAct",method = RequestMethod.POST)
    @ResponseBody
    public PageUtil<ProcessDefinition> showAct(ProcessDefinition definition,
                                               String page, String limit) {
        ProcessDefinitionQuery processDefinitionQuery = repositoryService
                .createProcessDefinitionQuery();
        PageUtil<ProcessDefinition> pageUtils=new PageUtil<>();
        List<org.activiti.engine.repository.ProcessDefinition> processDefinitionList = null;
        if (definition != null) {
            if (!StringUtils.isEmpty(definition.getDeploymentId())) {
                processDefinitionQuery.deploymentId(definition.getDeploymentId());
            }
            if (!StringUtils.isEmpty(definition.getName())) {
                processDefinitionQuery.processDefinitionNameLike("%" + definition.getName() + "%");

            }
        }
        processDefinitionList = processDefinitionQuery.listPage(Integer.valueOf(limit) * (Integer.valueOf(page) - 1), Integer.valueOf(limit));
        long count = repositoryService.createDeploymentQuery().count();
        List<ProcessDefinition> list = new ArrayList<>();
        processDefinitionList
                .forEach(processDefinition -> list.add(new ProcessDefinition(processDefinition)));
        pageUtils.setCount((int) count);
        pageUtils.setData(list);
        return pageUtils;
    }
    /**
     * 新建流程
     * 方法此有所参考 感谢我参考原作者：liuruijie
     */
    @GetMapping(value = "goActiviti")
    public String goActiviti() throws UnsupportedEncodingException {
        Model model = repositoryService.newModel();

        String name = "新建流程";
        String description = "";
        int revision = 1;
        String key = "processKey";

        ObjectNode modelNode = objectMapper.createObjectNode();
        modelNode.put(ModelDataJsonConstants.MODEL_NAME, name);
        modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
        modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision);

        model.setName(name);
        model.setKey(key);
        model.setMetaInfo(modelNode.toString());

        repositoryService.saveModel(model);
        String id = model.getId();

        //完善ModelEditorSource
        ObjectNode editorNode = objectMapper.createObjectNode();
        editorNode.put("id", "canvas");
        editorNode.put("resourceId", "canvas");
        ObjectNode stencilSetNode = objectMapper.createObjectNode();
        stencilSetNode.put("namespace",
                "http://b3mn.org/stencilset/bpmn2.0#");
        editorNode.put("stencilset", stencilSetNode);
        repositoryService.addModelEditorSource(id, editorNode.toString().getBytes("utf-8"));
        return "redirect:/static/modeler.html?modelId=" + id;
    }


    @GetMapping(value = "/goActModel")
    public String goActModel(org.springframework.ui.Model model) {
        return "actModelList";
    }

    /**
     * 模型列表
     */
    @GetMapping(value = "showAm")
    @ResponseBody
    public PageUtil<ActModel> showModel(org.springframework.ui.Model model, ActModel actModel, String page,
                              String limit) {
        PageUtil<ActModel> pageUtils=new PageUtil<>();
        ModelQuery modelQuery = repositoryService.createModelQuery();
        if (actModel != null) {
            if (!StringUtils.isEmpty(actModel.getKey())) {
                modelQuery.modelKey(actModel.getKey());
            }
            if (!StringUtils.isEmpty(actModel.getName())) {
                modelQuery.modelNameLike("%" + actModel.getName() + "%");
            }
        }
        List<Model> models = modelQuery
                .listPage(Integer.valueOf(limit) * (Integer.valueOf(page) - 1), Integer.valueOf(limit));
        long count = repositoryService.createModelQuery().count();
        List<ActModel> list = new ArrayList<>();
        models.forEach(mo -> list.add(new ActModel(mo)));
        pageUtils.setCount((int) count);
        pageUtils.setData(list);
        return pageUtils;
    }
    /**
     * 发布流程
     */
    @PostMapping(value = "open")
    @ResponseBody
    public RestResponse open(String id) {
        String msg = "发布成功";
        RestResponse j = new RestResponse();
        j.setSuccess(true);
        try {
            Model modelData = repositoryService.getModel(id);
            byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());

            if (bytes == null) {
                return RestResponse.failure("模型为空");
            }
            JsonNode modelNode = null;
            modelNode = new ObjectMapper().readTree(bytes);
            BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
            if (model.getProcesses().size() == 0) {
                return RestResponse.failure("数据不符合要求");
            }
            byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);
            //发布流程
            String processName = modelData.getName() + ".bpmn20.xml";
            String convertToXML = new String(bpmnBytes);

            System.out.println(convertToXML);
            Deployment deployment = repositoryService.createDeployment()
                    .name(modelData.getName())
                    .addString(processName, new String(bpmnBytes, "UTF-8"))
                    .deploy();
            modelData.setDeploymentId(deployment.getId());
            repositoryService.saveModel(modelData);
        } catch (MyException e) {
            msg = "发布数失败";

        } catch (IOException e) {
            e.printStackTrace();
        }
        j.setMessage(msg);
        return j;
    }
    @PostMapping("delModel")
    @ResponseBody
    public RestResponse delModel(org.springframework.ui.Model model, String id) {
        FileInputStream inputStream = null;
        RestResponse j = new RestResponse();
        j.setSuccess(true);
        try {
            repositoryService.deleteModel(id);
            j.setMessage("删除成功");
        } catch (MyException e) {
            j.setMessage("删除失败");
            j.setSuccess(false);
            e.printStackTrace();
        }
        return j;
    }
    /**
     * 删除流程定义 级联 删除 流程节点绑定信息
     *
     * @param id
     * @return
     */
    @PostMapping("delDeploy")
    @ResponseBody
    public RestResponse delDeploy(String id) {
        try {
            List<ActivityImpl> activityList = actAssigneeService.getActivityList(id);
            if (activityList != null) {
                for (ActivityImpl activity : activityList) {
                    String nodeId = activity.getId();
                    if (StringUtils.isEmpty(nodeId) || "start".equals(nodeId) || "end".equals(nodeId)) {
                        continue;
                    }
                    /**接触节点和代办关联*/
                    QueryWrapper<ActAssignee> queryWrapper=new QueryWrapper<>();
                    queryWrapper.eq("sid",nodeId);
                    ActAssignee actAssignee=actAssigneeService.getOne(queryWrapper);
                    if (actAssignee!=null) {
                        actAssigneeService.removeById(actAssignee.getId());
                    }
                }
            }
            org.activiti.engine.repository.ProcessDefinition processDefinition = repositoryService
                    .createProcessDefinitionQuery()
                    .processDefinitionId(id)
                    .singleResult();
            repositoryService.deleteDeployment(processDefinition.getDeploymentId(), true);
        } catch (MyException e) {
            RestResponse.failure("删除失败");
            e.printStackTrace();
        }
        return RestResponse.success();
    }




}
